package util

import (
	"crypto/cipher"
	"crypto/rand"
	"encoding/hex"
	"github.com/emmansun/gmsm/padding"
	"github.com/emmansun/gmsm/sm4"
	"io"
)

// 模仿获取sm4加密密钥
func SecretKey() string {
	return "1234567890ABCDEF1234567890ABCDEF"
}

func Sm4EncryptCBC(text, keyIn string) string {
	key, _ := hex.DecodeString(keyIn)
	plaintext := []byte(text)

	block, err := sm4.NewCipher(key)
	if err != nil {
		panic(err)
	}

	// CBC mode works on blocks so plaintexts may need to be padded to the
	// next whole block. For an example of such padding, see
	// https://tools.ietf.org/html/rfc5246#section-6.2.3.2.
	pkcs7 := padding.NewPKCS7Padding(sm4.BlockSize)
	paddedPlainText := pkcs7.Pad(plaintext)

	// The IV needs to be unique, but not secure. Therefore it's common to
	// include it at the beginning of the ciphertext.
	ciphertext := make([]byte, sm4.BlockSize+len(paddedPlainText))
	iv := ciphertext[:sm4.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		panic(err)
	}

	mode := cipher.NewCBCEncrypter(block, iv)
	mode.CryptBlocks(ciphertext[sm4.BlockSize:], paddedPlainText)

	//fmt.Printf("%x\n", ciphertext)
	return hex.EncodeToString(ciphertext)
}

func Sm4DecryptCBC(cipherText, keyIn string) string {
	key, _ := hex.DecodeString(keyIn)
	ciphertext, _ := hex.DecodeString(cipherText)

	block, err := sm4.NewCipher(key)
	if err != nil {
		panic(err)
	}

	// The IV needs to be unique, but not secure. Therefore it's common to
	// include it at the beginning of the ciphertext.
	if len(ciphertext) < sm4.BlockSize {
		panic("ciphertext too short")
	}
	iv := ciphertext[:sm4.BlockSize]
	ciphertext = ciphertext[sm4.BlockSize:]

	mode := cipher.NewCBCDecrypter(block, iv)

	// CryptBlocks can work in-place if the two arguments are the same.
	mode.CryptBlocks(ciphertext, ciphertext)

	// Unpad plaintext
	pkcs7 := padding.NewPKCS7Padding(sm4.BlockSize)
	ciphertext, err = pkcs7.Unpad(ciphertext)
	if err != nil {
		panic(err)
	}

	//fmt.Printf("_________________________________%s\n", ciphertext)
	return string(ciphertext)
}
